#include "stdafx.h"
#include "ui_offset_dc.h"


_SSL_BEGIN
_SSUIL_BEGIN

UIOffScreenDC::UIOffScreenDC()
{
	hwnd_ = NULL;
	dc_ = NULL;
	mem_dc_ = NULL;
	mem_bitmap_ = NULL;
	mem_bitmap_pixels_ = NULL;
	mem_bitmap_pixels_cnt_ = 0;
	old_mem_bitmap_ = NULL;
	saved_mem_dc_ = -1;
}

UIOffScreenDC::~UIOffScreenDC()
{
	Uninit();
}

bool UIOffScreenDC::Init(HWND hwnd, const RECT *rt /*= NULL*/)
{
	if(hwnd == NULL)
		hwnd = ::GetDesktopWindow();

	if(!::IsWindow(hwnd))
		return false;

	Uninit();

	RECT rt_l;
	if(rt == NULL)
		rt = &rt_l;
	if(rt->right - rt->left <= 0 || rt->bottom - rt->top <= 0)
	{
		if(!::GetClientRect(hwnd, &rt_l))
			return false;
	}

	rt_ = *rt;

	dc_ = ::GetDC(hwnd);
	mem_dc_ = ::CreateCompatibleDC(dc_);

	BITMAPINFO bmp_info = {0};
	bmp_info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	bmp_info.bmiHeader.biBitCount = 32;
	bmp_info.bmiHeader.biWidth = rt->right - rt->left;
	bmp_info.bmiHeader.biHeight = rt->bottom - rt->top;
	bmp_info.bmiHeader.biPlanes = 1;
	bmp_info.bmiHeader.biCompression = BI_RGB;
	bmp_info.bmiHeader.biXPelsPerMeter = 0;
	bmp_info.bmiHeader.biYPelsPerMeter = 0;
	bmp_info.bmiHeader.biClrUsed = 0;
	bmp_info.bmiHeader.biClrImportant = 0;
	bmp_info.bmiHeader.biSizeImage = bmp_info.bmiHeader.biWidth * bmp_info.bmiHeader.biHeight
		* bmp_info.bmiHeader.biBitCount / 8;
	mem_bitmap_pixels_cnt_ = bmp_info.bmiHeader.biSizeImage;
	mem_bitmap_ = ::CreateDIBSection(mem_dc_, &bmp_info, 0, (void**)&mem_bitmap_pixels_, 0, 0);

	old_mem_bitmap_ = ::SelectObject(mem_dc_, mem_bitmap_);

	hwnd_ = hwnd;

	if(mem_bitmap_pixels_ != NULL)
	{
		memset(mem_bitmap_pixels_, 0, mem_bitmap_pixels_cnt_);
	}

	return true;
}

void UIOffScreenDC::Uninit()
{
	if(old_mem_bitmap_ != NULL)
	{
		::SelectObject(mem_dc_, mem_bitmap_);
		old_mem_bitmap_ = NULL;
	}

	if(mem_bitmap_ != NULL)
	{
		::DeleteObject(mem_bitmap_);
		mem_bitmap_ = NULL;
	}

	if(mem_dc_ != NULL)
	{
		::DeleteObject(mem_dc_);
		mem_dc_ = NULL;
	}

	if(dc_ == NULL)
	{
		::ReleaseDC(hwnd_, dc_);
	}

	mem_bitmap_pixels_ = NULL;
	mem_bitmap_pixels_cnt_ = 0;
}

HDC UIOffScreenDC::GetDC()
{
	if(mem_bitmap_pixels_ != NULL)
	{
		unsigned char *ptr = (unsigned char*)mem_bitmap_pixels_;
		for(size_t i=0; i<mem_bitmap_pixels_cnt_;)
		{
			ptr[i + 0] = 0xFF; // B
			ptr[i + 1] = 0xFF; // G
			ptr[i + 2] = 0xFF; // R
			ptr[i + 3] = 0x00; // A
			i+=4;
		}
	}
	saved_mem_dc_ = ::SaveDC(mem_dc_);
	return mem_dc_;
}

void UIOffScreenDC::ReleaseDC()
{
	if(saved_mem_dc_ != -1)
	{
		::RestoreDC(mem_dc_, saved_mem_dc_);
		saved_mem_dc_ = -1;
	}
}

HDC UIOffScreenDC::GetCachedDC()
{
	return mem_dc_;
}

int UIOffScreenDC::GetWidth() const
{
	return rt_.right - rt_.left;
}

int UIOffScreenDC::GetHeight() const
{
	return rt_.bottom - rt_.top;
}

HBITMAP UIOffScreenDC::GetMemBitmap()
{
	return mem_bitmap_;
}

_SSUIL_END
_SSL_END
